using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Routing;
using System.Web.Mvc;
using Nop.Core;
using Nop.Core.Domain;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.Directory;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Payments;
using Nop.Core.Domain.Shipping;
using Nop.Core.Plugins;
using Nop.Plugin.Payments.PayPalExpress.Controllers;
using Nop.Plugin.Payments.PayPalExpress.PayPalSvc;
using Nop.Services.Common;
using Nop.Services.Configuration;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.Localization;
using Nop.Services.Orders;
using Nop.Services.Payments;
using Nop.Services.Tax;
using Nop.Services.Logging;

namespace Nop.Plugin.Payments.PayPalExpress
{
    /// <summary>
    /// PayPalExpress payment processor
    /// </summary>
    public class PayPalExpressCheckoutPaymentProcessor : BasePlugin, IPaymentMethod
    {

        #region Fields

        private readonly PayPalExpressCheckoutPaymentSettings _paypalExpressCheckoutPaymentSettings;
        private readonly ISettingService _settingService;
        private readonly ICurrencyService _currencyService;
        private readonly CurrencySettings _currencySettings;
        private readonly IWebHelper _webHelper;
        private readonly ICheckoutAttributeParser _checkoutAttributeParser;
        private readonly ITaxService _taxService;
        private readonly HttpContextBase _httpContext;
        private readonly IOrderService _orderService;
        private readonly IStateProvinceService _stateProvinceService;
        private readonly ICountryService _countryService;
        private readonly ICustomerService _customerService;
        private readonly IOrderTotalCalculationService _orderTotalCalculationService;
        private readonly IWorkContext _workContext;
        private readonly ILogger _logger;

        #endregion

        #region Ctor

        public PayPalExpressCheckoutPaymentProcessor(PayPalExpressCheckoutPaymentSettings paypalExpressCheckoutPaymentSettings,
            ISettingService settingService, ICurrencyService currencyService,
            CurrencySettings currencySettings, IWebHelper webHelper,
            ICheckoutAttributeParser checkoutAttributeParser, ITaxService taxService,
            HttpContextBase httpContext, IOrderService orderService, IStateProvinceService stateProvinceService,
            ICountryService countryService, ICustomerService customerService, IOrderTotalCalculationService orderTotalCalculationService, IWorkContext workContext, ILogger logger)
        {
            this._paypalExpressCheckoutPaymentSettings = paypalExpressCheckoutPaymentSettings;
            this._settingService = settingService;
            this._currencyService = currencyService;
            this._currencySettings = currencySettings;
            this._webHelper = webHelper;
            this._checkoutAttributeParser = checkoutAttributeParser;
            this._taxService = taxService;
            this._httpContext = httpContext;
            this._orderService = orderService;
            this._stateProvinceService = stateProvinceService;
            this._countryService = countryService;
            this._customerService = customerService;
            this._orderTotalCalculationService = orderTotalCalculationService;
            this._workContext = workContext;
            this._logger = logger;
        }

        #endregion

        #region Utilities

        /// <summary>
        /// Gets Paypal URL
        /// </summary>
        /// <returns></returns>
        private string GetPaypalUrl()
        {
            return _paypalExpressCheckoutPaymentSettings.UseSandbox ? "https://www.sandbox.paypal.com/us/cgi-bin/webscr" :
                "https://www.paypal.com/us/cgi-bin/webscr";
        }

        /// <summary>
        /// Get Paypal country code
        /// </summary>
        /// <param name="country">Country</param>
        /// <returns>Paypal country code</returns>
        protected CountryCodeType GetPaypalCountryCodeType(Country country)
        {
            CountryCodeType payerCountry = CountryCodeType.US;
            try
            {
                payerCountry = (CountryCodeType)Enum.Parse(typeof(CountryCodeType), country.TwoLetterIsoCode);
            }
            catch
            {
            }
            return payerCountry;
        }

        /// <summary>
        /// Get Paypal credit card type
        /// </summary>
        /// <param name="CreditCardType">Credit card type</param>
        /// <returns>Paypal credit card type</returns>
        protected CreditCardTypeType GetPaypalCreditCardType(string CreditCardType)
        {
            CreditCardTypeType creditCardTypeType = (CreditCardTypeType)Enum.Parse(typeof(CreditCardTypeType), CreditCardType);
            return creditCardTypeType;
            //if (CreditCardType.ToLower() == "visa")
            //    return CreditCardTypeType.Visa;

            //if (CreditCardType.ToLower() == "mastercard")
            //    return CreditCardTypeType.MasterCard;

            //if (CreditCardType.ToLower() == "americanexpress")
            //    return CreditCardTypeType.Amex;

            //if (CreditCardType.ToLower() == "discover")
            //    return CreditCardTypeType.Discover;

            //throw new NopException("Unknown credit card type");
        }

        protected string GetApiVersion()
        {
            return "78";
        }

        /// <summary>
        /// Gets PDT details
        /// </summary>
        /// <param name="tx">TX</param>
        /// <param name="values">Values</param>
        /// <param name="response">Response</param>
        /// <returns>Result</returns>
        public bool GetPDTDetails(string tx, out Dictionary<string, string> values, out string response)
        {
            var req = (HttpWebRequest)WebRequest.Create(GetPaypalUrl());
            req.Method = "POST";
            req.ContentType = "application/x-www-form-urlencoded";

            string formContent = string.Format("cmd=_notify-synch&at={0}&tx={1}", _paypalExpressCheckoutPaymentSettings.PdtToken, tx);
            req.ContentLength = formContent.Length;

            using (var sw = new StreamWriter(req.GetRequestStream(), Encoding.ASCII))
                sw.Write(formContent);

            response = null;
            using (var sr = new StreamReader(req.GetResponse().GetResponseStream()))
                response = HttpUtility.UrlDecode(sr.ReadToEnd());

            values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            bool firstLine = true, success = false;
            foreach (string l in response.Split('\n'))
            {
                string line = l.Trim();
                if (firstLine)
                {
                    success = line.Equals("SUCCESS", StringComparison.OrdinalIgnoreCase);
                    firstLine = false;
                }
                else
                {
                    int equalPox = line.IndexOf('=');
                    if (equalPox >= 0)
                        values.Add(line.Substring(0, equalPox), line.Substring(equalPox + 1));
                }
            }

            return success;
        }

        /// <summary>
        /// Verifies IPN
        /// </summary>
        /// <param name="formString">Form string</param>
        /// <param name="values">Values</param>
        /// <returns>Result</returns>
        public bool VerifyIPN(string formString, out Dictionary<string, string> values)
        {
            var req = (HttpWebRequest)WebRequest.Create(GetPaypalUrl());
            req.Method = "POST";
            req.ContentType = "application/x-www-form-urlencoded";

            string formContent = string.Format("{0}&cmd=_notify-validate", formString);
            req.ContentLength = formContent.Length;

            using (var sw = new StreamWriter(req.GetRequestStream(), Encoding.ASCII))
            {
                sw.Write(formContent);
            }

            string response = null;
            using (var sr = new StreamReader(req.GetResponse().GetResponseStream()))
            {
                response = HttpUtility.UrlDecode(sr.ReadToEnd());
            }
            bool success = response.Trim().Equals("VERIFIED", StringComparison.OrdinalIgnoreCase);

            values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            foreach (string l in formString.Split('&'))
            {
                string line = l.Trim();
                int equalPox = line.IndexOf('=');
                if (equalPox >= 0)
                    values.Add(line.Substring(0, equalPox), line.Substring(equalPox + 1));
            }

            return success;
        }

        #endregion

        #region Methods

        public GetExpressCheckoutDetailsResponseType GetExpressCheckoutDetails(string token)
        {
            var result = new GetExpressCheckoutDetailsResponseType();
            using (var service2 = new PayPalAPIAASoapBinding())
            {
                var req = new GetExpressCheckoutDetailsReq();
                req.GetExpressCheckoutDetailsRequest = new GetExpressCheckoutDetailsRequestType
                {
                    Token = token,
                    Version = GetApiVersion()
                };

                service2.Url = !_paypalExpressCheckoutPaymentSettings.UseSandbox ? "https://api-3t.paypal.com/2.0/" : "https://api-3t.sandbox.paypal.com/2.0/";

                service2.RequesterCredentials = new CustomSecurityHeaderType
                {
                    Credentials = new UserIdPasswordType
                    {
                        Username = _paypalExpressCheckoutPaymentSettings.ApiAccountName,
                        Password = _paypalExpressCheckoutPaymentSettings.ApiAccountPassword,
                        Signature = _paypalExpressCheckoutPaymentSettings.Signature,
                        Subject = ""
                    }
                };

                result = service2.GetExpressCheckoutDetails(req);
            }
            return result;
        }

        public DoExpressCheckoutPaymentResponseType DoExpressCheckoutPayment(ProcessPaymentRequest processPaymentRequest)
        {
            var result = new DoExpressCheckoutPaymentResponseType();

            // populate payment details
            var paymentDetails = new PaymentDetailsType
            {
                OrderTotal = new BasicAmountType
                {
                    Value = Math.Round(processPaymentRequest.OrderTotal, 2).ToString("N", new CultureInfo("en-us")),
                    currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
                },
                Custom = processPaymentRequest.OrderGuid.ToString(),
                ButtonSource = "nopCommerceCart"
            };

            // build the request
            var req = new DoExpressCheckoutPaymentReq
            {
                DoExpressCheckoutPaymentRequest = new DoExpressCheckoutPaymentRequestType
                {
                    Version = GetApiVersion(),
                    DoExpressCheckoutPaymentRequestDetails = new DoExpressCheckoutPaymentRequestDetailsType
                    {
                        Token = processPaymentRequest.PaypalToken,
                        PayerID = processPaymentRequest.PaypalPayerId,
                        PaymentAction = PaymentActionCodeType.Sale,
                        PaymentDetails = new PaymentDetailsType[]
                        {
                            paymentDetails
                        }
                    }
                }
            };

            //execute request
            using (var service2 = new PayPalAPIAASoapBinding())
            {
                service2.Url = !_paypalExpressCheckoutPaymentSettings.UseSandbox ? "https://api-3t.paypal.com/2.0/" : "https://api-3t.sandbox.paypal.com/2.0/";

                service2.RequesterCredentials = new CustomSecurityHeaderType
                {
                    Credentials = new UserIdPasswordType
                    {
                        Username = _paypalExpressCheckoutPaymentSettings.ApiAccountName,
                        Password = _paypalExpressCheckoutPaymentSettings.ApiAccountPassword,
                        Signature = _paypalExpressCheckoutPaymentSettings.Signature,
                        Subject = ""
                    }
                };

                result = service2.DoExpressCheckoutPayment(req);
            }
            return result;
        }

        public SetExpressCheckoutResponseType SetExpressCheckout(ProcessPaymentRequest processPaymentRequest, List<ShoppingCartItem> cart )
        {
            var result = new SetExpressCheckoutResponseType();

            // initialize ExpressCheckout object
            var req = new SetExpressCheckoutReq
            {
                SetExpressCheckoutRequest = new SetExpressCheckoutRequestType
                {
                    Version = GetApiVersion(),
                    SetExpressCheckoutRequestDetails = new SetExpressCheckoutRequestDetailsType()
                }
            };

            // build ExpressCheckout details
            var details = new SetExpressCheckoutRequestDetailsType
            {
                PaymentAction = PaymentActionCodeType.Authorization,
                CancelURL = _webHelper.GetStoreLocation(_webHelper.SslEnabled()) + "cart",
                ReturnURL = _webHelper.GetStoreLocation(_webHelper.SslEnabled()) + "Plugins/PaymentPayPalExpress/GetDetails"
            };

            // populate cart
            decimal cartTotal = decimal.Zero;
            //var cartItems = order.OrderProductVariants;
            int x = 0;
            var paymentDetailItems = new PaymentDetailsItemType[cart.Count];
            foreach (var item in cart)
            {
                var unitPriceExclTax = item.ProductVariant.Price;
                var priceExclTax = unitPriceExclTax * item.Quantity;
                //round
                var unitPriceExclTaxRounded = Math.Round(unitPriceExclTax, 2);

                paymentDetailItems[x] = new PaymentDetailsItemType()
                {
                    Name = item.ProductVariant.FullProductName,
                    Number = item.ProductVariant.Sku,
                    Quantity = item.Quantity.ToString(CultureInfo.InvariantCulture),
                    Amount = new BasicAmountType()  // this is the per item cost
                    {
                        currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)),
                        Value = (Math.Round(unitPriceExclTaxRounded, 2)).ToString("N", new CultureInfo("en-us"))
                    }
                };
                cartTotal += priceExclTax;
                x++;
            };

            // get shipping costs
            decimal shippingTotal = decimal.Zero;
            if (cart.RequiresShipping())
            {
                decimal? shoppingCartShippingBase = _orderTotalCalculationService.GetShoppingCartShippingTotal(cart);
                if (shoppingCartShippingBase.HasValue)
                {
                    shippingTotal = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartShippingBase.Value, _workContext.WorkingCurrency);
                }
            }

            // get total tax
            SortedDictionary<decimal, decimal> taxRates = null;
            decimal shoppingCartTaxBase = _orderTotalCalculationService.GetTaxTotal(cart, out taxRates);
            decimal shoppingCartTax = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTaxBase, _workContext.WorkingCurrency);

            // populate payment details
            decimal discount = processPaymentRequest.OrderTotal - (cartTotal + shippingTotal + shoppingCartTax);

            var paymentDetails = new PaymentDetailsType
            {
                ItemTotal = new BasicAmountType
                {
                    Value = Math.Round(cartTotal, 2).ToString("N", new CultureInfo("en-us")),
                    currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
                },
                ShippingTotal = new BasicAmountType
                {
                    Value = Math.Round(shippingTotal, 2).ToString("N", new CultureInfo("en-us")),
                    currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
                },
                TaxTotal = new BasicAmountType
                {
                    Value = Math.Round(shoppingCartTax, 2).ToString("N", new CultureInfo("en-us")),
                    currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
                },
                ShippingDiscount = new BasicAmountType
                {
                    Value = Math.Round(discount, 2).ToString("N", new CultureInfo("en-us")),
                    currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
                },
                OrderTotal = new BasicAmountType
                {
                    Value = Math.Round(processPaymentRequest.OrderTotal, 2).ToString("N", new CultureInfo("en-us")),
                    currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId))
                },
                Custom = processPaymentRequest.OrderGuid.ToString(),
                ButtonSource = "nopCommerceCart",
                PaymentDetailsItem = paymentDetailItems
            };

            details.PaymentDetails = new[] { paymentDetails };
            req.SetExpressCheckoutRequest.SetExpressCheckoutRequestDetails.Custom = processPaymentRequest.OrderGuid.ToString();
            req.SetExpressCheckoutRequest.SetExpressCheckoutRequestDetails = details;

            using (var service2 = new PayPalAPIAASoapBinding())
            {
                service2.Url = !_paypalExpressCheckoutPaymentSettings.UseSandbox ? "https://api-3t.paypal.com/2.0/" : "https://api-3t.sandbox.paypal.com/2.0/";

                service2.RequesterCredentials = new CustomSecurityHeaderType
                {
                    Credentials = new UserIdPasswordType
                    {
                        Username = _paypalExpressCheckoutPaymentSettings.ApiAccountName,
                        Password = _paypalExpressCheckoutPaymentSettings.ApiAccountPassword,
                        Signature = _paypalExpressCheckoutPaymentSettings.Signature,
                        Subject = ""
                    }
                };

                result = service2.SetExpressCheckout(req);

            }
            return result;
        }

        public ProcessPaymentRequest SetCheckoutDetails(ProcessPaymentRequest processPaymentRequest, GetExpressCheckoutDetailsResponseDetailsType checkoutDetails)
        {
            // get customer & cart
            var customer = _customerService.GetCustomerById(processPaymentRequest.CustomerId);
            //var cart = customer.ShoppingCartItems.Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart).ToList();
            #region Create Address
            //if (!_workContext.CurrentCustomer.IsRegistered())
            //{
            //    var country_new = new Country();
            //    var stateProvince_new = new StateProvince();
            //    // get/update billing address
            //    string billingFirstName = checkoutDetails.PayerInfo.PayerName.FirstName;
            //    string billingLastName = checkoutDetails.PayerInfo.PayerName.LastName;
            //    string billingEmail = checkoutDetails.PayerInfo.Payer;
            //    string billingAddress1 = checkoutDetails.PayerInfo.Address.Street1;
            //    string billingAddress2 = checkoutDetails.PayerInfo.Address.Street2;
            //    string billingPhoneNumber = checkoutDetails.PayerInfo.Address.Phone;
            //    string billingCity = checkoutDetails.PayerInfo.Address.CityName;
            //    string billingZipPostalCode = checkoutDetails.PayerInfo.Address.PostalCode;
            //    int? billingCountryId = null;
            //    var billingCountry = _countryService.GetCountryByTwoLetterIsoCode(checkoutDetails.PayerInfo.Address.Country.ToString());
            //    if (billingCountry != null)
            //    {
            //        billingCountryId = billingCountry.Id;
            //    }
            //    else 
            //    {
            //        country_new.AllowsBilling = true;
            //        country_new.AllowsShipping = true;
            //        country_new.Name = checkoutDetails.PayerInfo.Address.CountryName;
            //        country_new.Published = true;
            //        //country_new.RestrictedShippingMethods=
            //        //billingAddress.Country = country_new;
            //        billingCountryId = country_new.Id;
            //    }
            //    int? billingStateProvinceId = null;
            //    var billingStateProvince = _stateProvinceService.GetStateProvinceByAbbreviation(checkoutDetails.PayerInfo.Address.StateOrProvince);
            //    if (billingStateProvince != null)
            //    {
            //        billingStateProvinceId = billingStateProvince.Id;
            //    }
            //    else
            //    {
            //        stateProvince_new.Abbreviation = checkoutDetails.PayerInfo.Address.StateOrProvince;
            //        stateProvince_new.CountryId = country_new.Id;
            //        stateProvince_new.Name = checkoutDetails.PayerInfo.Address.StateOrProvince;
            //        stateProvince_new.Published = true;
            //        //billingAddress.StateProvince = stateProvince_new;
            //        billingStateProvinceId = stateProvince_new.Id;
            //    }
            //    var billingAddress = customer.Addresses.ToList().FindAddress(
            //        billingFirstName, billingLastName, billingPhoneNumber,
            //        billingEmail, string.Empty, string.Empty, billingAddress1, billingAddress2, billingCity,
            //        billingStateProvinceId, billingZipPostalCode, billingCountryId);

            //    if (billingAddress == null)
            //    {
            //        billingAddress = new Address()
            //        {
            //            FirstName = billingFirstName,
            //            LastName = billingLastName,
            //            PhoneNumber = billingPhoneNumber,
            //            Email = billingEmail,
            //            Address1 = billingAddress1,
            //            Address2 = billingAddress2,
            //            City = billingCity,
            //            StateProvinceId = billingStateProvinceId,
            //            StateProvince = billingStateProvince != null?billingStateProvince:stateProvince_new,
            //            ZipPostalCode = billingZipPostalCode,
            //            CountryId = billingCountryId,
            //            Country = billingCountry!=null?billingCountry:country_new,
            //            CreatedOnUtc = DateTime.UtcNow,
            //        };
            //        customer.Addresses.Add(billingAddress);
            //    }
            //    //set default billing address
            //    customer.SetBillingAddress(billingAddress);
            //    _customerService.UpdateCustomer(customer);

            //    _customerService.SaveCustomerAttribute<ShippingOption>(customer, SystemCustomerAttributeNames.LastShippingOption, null);

            //    bool shoppingCartRequiresShipping = cart.RequiresShipping();
            //    if (shoppingCartRequiresShipping)
            //    {
            //        var paymentDetails = checkoutDetails.PaymentDetails.FirstOrDefault();

            //        var shipAddress = new AddressType();
            //        var shippingFirstName = string.Empty;
            //        var shippingLastName = string.Empty;
            //        var shippingEmail = string.Empty;
            //        var shippingAddress1 = string.Empty;
            //        var shippingAddress2 = string.Empty;
            //        var shippingPhoneNumber = string.Empty;
            //        var shippingCity = string.Empty;
            //        int? shippingStateProvinceId = null;
            //        int? shippingCountryId = null;
            //        var shippingZipPostalCode = string.Empty;

            //        if (paymentDetails == null)
            //        {
            //            shippingFirstName = checkoutDetails.PayerInfo.PayerName.FirstName;
            //            shippingLastName = checkoutDetails.PayerInfo.PayerName.LastName;
            //            shippingEmail = checkoutDetails.PayerInfo.Payer;
            //            shippingAddress1 = checkoutDetails.PayerInfo.Address.Street1;
            //            shippingAddress2 = checkoutDetails.PayerInfo.Address.Street2;
            //            shippingPhoneNumber = checkoutDetails.PayerInfo.ContactPhone;
            //            shippingCity = checkoutDetails.PayerInfo.Address.CityName;
            //            shippingZipPostalCode = checkoutDetails.PayerInfo.Address.PostalCode;
            //            var shippingCountry =
            //                _countryService.GetCountryByTwoLetterIsoCode(
            //                    checkoutDetails.PayerInfo.Address.Country.ToString());
            //            if (shippingCountry != null)
            //            {
            //                shippingCountryId = shippingCountry.Id;
            //            }
            //            else
            //            {
            //                country_new.AllowsBilling = true;
            //                country_new.AllowsShipping = true;
            //                country_new.Name = checkoutDetails.PayerInfo.Address.CountryName;
            //                country_new.Published = true;
            //                //country_new.RestrictedShippingMethods=
            //                //billingAddress.Country = country_new;
            //                shippingCountryId = country_new.Id;
            //            }
            //            var shippingStateProvince =
            //                _stateProvinceService.GetStateProvinceByAbbreviation(
            //                    checkoutDetails.PayerInfo.Address.StateOrProvince);
            //            if (shippingStateProvince != null)
            //            {
            //                shippingStateProvinceId = shippingStateProvince.Id;
            //            }
            //            else
            //            {
            //                stateProvince_new.Abbreviation = checkoutDetails.PayerInfo.Address.StateOrProvince;
            //                stateProvince_new.CountryId = country_new.Id;
            //                stateProvince_new.Name = checkoutDetails.PayerInfo.Address.StateOrProvince;
            //                stateProvince_new.Published = true;
            //                //billingAddress.StateProvince = stateProvince_new;
            //                shippingStateProvinceId = stateProvince_new.Id;
            //            }
            //        }
            //        else
            //        {
            //            shipAddress = paymentDetails.ShipToAddress;
            //            string[] shippingFullname = shipAddress.Name.Trim().Split(new char[] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);
            //            shippingFirstName = shippingFullname[0];
            //            shippingLastName = checkoutDetails.PayerInfo.PayerName.LastName;
            //            if (shippingFullname.Length > 1)
            //                shippingLastName = shippingFullname[1];
            //            shippingEmail = checkoutDetails.PayerInfo.Payer;
            //            shippingAddress1 = shipAddress.Street1;
            //            shippingAddress2 = shipAddress.Street2;
            //            shippingPhoneNumber = shipAddress.Phone;
            //            shippingCity = shipAddress.CityName;
                        
            //            shippingZipPostalCode = shipAddress.PostalCode;
            //            var shippingCountry = _countryService.GetCountryByTwoLetterIsoCode(shipAddress.Country.ToString());
            //            if (shippingCountry != null)
            //            {
            //                shippingCountryId = shippingCountry.Id;
            //            }
            //            else
            //            {
            //                country_new.AllowsBilling = true;
            //                country_new.AllowsShipping = true;
            //                country_new.Name = checkoutDetails.PayerInfo.Address.CountryName;
            //                country_new.Published = true;
            //                //country_new.RestrictedShippingMethods=
            //                //billingAddress.Country = country_new;
            //                shippingCountryId = country_new.Id;
            //            }
            //            var shippingStateProvince = _stateProvinceService.GetStateProvinceByAbbreviation(shipAddress.StateOrProvince);
            //            if (shippingStateProvince != null)
            //            {
            //                shippingStateProvinceId = shippingStateProvince.Id;
            //            }
            //            else
            //            {
            //                stateProvince_new.Abbreviation = checkoutDetails.PayerInfo.Address.StateOrProvince;
            //                stateProvince_new.CountryId = country_new.Id;
            //                stateProvince_new.Name = checkoutDetails.PayerInfo.Address.StateOrProvince;
            //                stateProvince_new.Published = true;
            //                //billingAddress.StateProvince = stateProvince_new;
            //                shippingStateProvinceId = stateProvince_new.Id;
            //            }
            //        }
            //        //var shippingAddress = customer.Addresses.ToList().FindAddress(
            //        //    shippingFirstName, shippingLastName, shippingPhoneNumber,
            //        //    shippingEmail, string.Empty, string.Empty,
            //        //    shippingAddress1, shippingAddress2, shippingCity,
            //        //    shippingStateProvinceId, shippingZipPostalCode, shippingCountryId);
            //        //if (shippingAddress == null)
            //        //{
            //        var shippingAddress = new Address()
            //         {
            //             FirstName = shippingFirstName,
            //             LastName = shippingLastName,
            //             PhoneNumber = shippingPhoneNumber,
            //             Email = shippingEmail,
            //             Address1 = shippingAddress1,
            //             Address2 = shippingAddress2,
            //             City = shippingCity,
            //             StateProvinceId = shippingStateProvinceId,
            //             StateProvince = billingStateProvince != null ? billingStateProvince : stateProvince_new,
            //             ZipPostalCode = shippingZipPostalCode,
            //             CountryId = shippingCountryId,
            //             Country = billingCountry != null ? billingCountry : country_new,
            //             CreatedOnUtc = DateTime.UtcNow,
            //         };
            //        customer.Addresses.Add(shippingAddress);
            //        //}
            //        //set default shipping address
            //        customer.SetShippingAddress(shippingAddress);
            //        _customerService.UpdateCustomer(customer);
            //    }
            //}
            #endregion

            processPaymentRequest.CustomerId = customer.Id;
            processPaymentRequest.PaypalPayerId = checkoutDetails.PayerInfo.PayerID;
            return processPaymentRequest;
        }


        /// <summary>
        /// Process a payment
        /// </summary>
        /// <param name="processPaymentRequest">Payment info required for an order processing</param>
        /// <returns>Process payment result</returns>
        public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentRequest)
        {
            var doPayment = DoExpressCheckoutPayment(processPaymentRequest);
            var result = new ProcessPaymentResult();

            if (doPayment.Ack == AckCodeType.Success)
            {
                result.NewPaymentStatus = PaymentStatus.Paid;
                result.AuthorizationTransactionId = processPaymentRequest.PaypalToken;
                result.CaptureTransactionId = doPayment.DoExpressCheckoutPaymentResponseDetails.PaymentInfo.FirstOrDefault().TransactionID;
                result.CaptureTransactionResult = doPayment.Ack.ToString();
            }
            else
            {
                result.NewPaymentStatus = PaymentStatus.Pending;
            }

            return result;
        }

        /// <summary>
        /// Post process payment (used by payment gateways that require redirecting to a third-party URL)
        /// </summary>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        public void PostProcessPayment(PostProcessPaymentRequest postProcessPaymentRequest)
        {
        }

        /// <summary>
        /// Gets additional handling fee
        /// </summary>
        /// <returns>Additional handling fee</returns>
        public decimal GetAdditionalHandlingFee()
        {
            return _paypalExpressCheckoutPaymentSettings.AdditionalFee;
        }

        /// <summary>
        /// Captures payment
        /// </summary>
        /// <param name="capturePaymentRequest">Capture payment request</param>
        /// <returns>Capture payment result</returns>
        public CapturePaymentResult Capture(CapturePaymentRequest capturePaymentRequest)
        {
            var result = new CapturePaymentResult();
            result.AddError("Capture method not supported");
            return result;
        }

        /// <summary>
        /// Refunds a payment
        /// </summary>
        /// <param name="refundPaymentRequest">Request</param>
        /// <returns>Result</returns>
        public RefundPaymentResult Refund(RefundPaymentRequest refundPaymentRequest)
        {
            var result = new RefundPaymentResult();
            result.AddError("Refund method not supported");
            return result;
        }

        /// <summary>
        /// Voids a payment
        /// </summary>
        /// <param name="voidPaymentRequest">Request</param>
        /// <returns>Result</returns>
        public VoidPaymentResult Void(VoidPaymentRequest voidPaymentRequest)
        {
            var result = new VoidPaymentResult();
            result.AddError("Void method not supported");
            return result;
        }

        /// <summary>
        /// Process recurring payment
        /// </summary>
        /// <param name="processPaymentRequest">Payment info required for an order processing</param>
        /// <returns>Process payment result</returns>
        public ProcessPaymentResult ProcessRecurringPayment(ProcessPaymentRequest processPaymentRequest)
        {
            var result = new ProcessPaymentResult();
            result.AddError("Recurring payment not supported");
            return result;
        }

        /// <summary>
        /// Cancels a recurring payment
        /// </summary>
        /// <param name="cancelPaymentRequest">Request</param>
        /// <returns>Result</returns>
        public CancelRecurringPaymentResult CancelRecurringPayment(CancelRecurringPaymentRequest cancelPaymentRequest)
        {
            var result = new CancelRecurringPaymentResult();
            result.AddError("Recurring payment not supported");
            return result;
        }

        /// <summary>
        /// Gets a value indicating whether customers can complete a payment after order is placed but not completed (for redirection payment methods)
        /// </summary>
        /// <param name="order">Order</param>
        /// <returns>Result</returns>
        public bool CanRePostProcessPayment(Order order)
        {
            if (order == null)
                throw new ArgumentNullException("order");

            //PayPal Express is the redirection payment method
            //It also validates whether order is also paid (after redirection) so customers will not be able to pay twice

            //payment status should be Pending
            if (order.PaymentStatus != PaymentStatus.Pending)
                return false;

            //let's ensure that at least 1 minute passed after order is placed
            if ((DateTime.UtcNow - order.CreatedOnUtc).TotalMinutes < 1)
                return false;

            return true;
        }

        /// <summary>
        /// Gets a route for provider configuration
        /// </summary>
        /// <param name="actionName">Action name</param>
        /// <param name="controllerName">Controller name</param>
        /// <param name="routeValues">Route values</param>
        public void GetConfigurationRoute(out string actionName, out string controllerName, out RouteValueDictionary routeValues)
        {
            actionName = "Configure";
            controllerName = "PaymentPayPalExpress";
            routeValues = new RouteValueDictionary() { { "Namespaces", "Nop.Plugin.Payments.PaymentPayPalExpressController.Controllers" }, { "area", null } };
        }

        /// <summary>
        /// Gets a route for payment info
        /// </summary>
        /// <param name="actionName">Action name</param>
        /// <param name="controllerName">Controller name</param>
        /// <param name="routeValues">Route values</param>
        public void GetPaymentInfoRoute(out string actionName, out string controllerName, out RouteValueDictionary routeValues)
        {
            actionName = "PaymentInfo";
            controllerName = "PaymentPayPalExpress";
            routeValues = new RouteValueDictionary() { { "Namespaces", "Nop.Plugin.Payments.PaymentPayPalExpressController.Controllers" }, { "area", null } };
        }

        public Type GetControllerType()
        {
            return typeof(PaymentPayPalExpressController);
        }

        public override void Install()
        {
            //settings
            var settings = new PayPalExpressCheckoutPaymentSettings()
            {
                UseSandbox = true,
                //BusinessEmail = "test@test.com",
                TransactMode = TransactMode.Authorize,
                PdtToken = "Your PDT token here...",
                PdtValidateOrderTotal = true,
                EnableIpn = true,
            };
            _settingService.SaveSetting(settings);

            //locales
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.RedirectionTip", "You will be redirected to PayPal site to complete the order.");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.UseSandbox", "Use Sandbox");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.UseSandbox.Hint", "Check to enable Sandbox (testing environment).");

            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.ApiAccountName", "API Username");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.ApiAccountName.Hint", "Enter the API Username from you PayPal account.");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.ApiAccountPassword", "API Password");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.ApiAccountPassword.Hint", "Enter the API Password from you PayPal account.");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.Signature", "API Signature");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.Signature.Hint", "Enter the API Signature from your PayPal account.");

            //this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.BusinessEmail", "Business Email");
            //this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.BusinessEmail.Hint", "Specify your PayPal business email.");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.PDTToken", "PDT Identity Token");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.PDTToken.Hint", "Specify PDT identity token");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.PDTValidateOrderTotal", "PDT. Validate order total");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.PDTValidateOrderTotal.Hint", "Check if PDT handler should validate order totals.");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.AdditionalFee", "Additional fee");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.AdditionalFee.Hint", "Enter additional fee to charge your customers.");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.PassProductNamesAndTotals", "Pass product names and order totals to PayPal");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.PassProductNamesAndTotals.Hint", "Check if product names and order totals should be passed to PayPal.");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.EnableIpn", "Enable IPN (Instant Payment Notification)");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.EnableIpn.Hint", "Check if IPN is enabled.");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.EnableIpn.Hint2", "Leave blank to use the default IPN handler URL.");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.IpnUrl", "IPN Handler");
            this.AddOrUpdatePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.IpnUrl.Hint", "Specify IPN Handler.");

            base.Install();
        }

        public override void Uninstall()
        {
            //locales
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.RedirectionTip");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.UseSandbox");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.UseSandbox.Hint");

            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.ApiAccountName");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.ApiAccountName.Hint");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.ApiAccountPassword");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.ApiAccountPassword.Hint");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.Signature");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.Signature.Hint");
            //this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.BusinessEmail");
            //this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.BusinessEmail.Hint");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.PDTToken");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.PDTToken.Hint");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.PDTValidateOrderTotal");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.PDTValidateOrderTotal.Hint");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.AdditionalFee");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.AdditionalFee.Hint");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.PassProductNamesAndTotals");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.PassProductNamesAndTotals.Hint");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.EnableIpn");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.EnableIpn.Hint");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.EnableIpn.Hint2");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.IpnUrl");
            this.DeletePluginLocaleResource("Plugins.Payments.PayPalExpress.Fields.IpnUrl.Hint");

            base.Uninstall();
        }


        #endregion

        #region Properies
        public bool SupportCapture
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets a value indicating whether partial refund is supported
        /// </summary>
        public bool SupportPartiallyRefund
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets a value indicating whether refund is supported
        /// </summary>
        public bool SupportRefund
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets a value indicating whether void is supported
        /// </summary>
        public bool SupportVoid
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets a recurring payment type of payment method
        /// </summary>
        public RecurringPaymentType RecurringPaymentType
        {
            get
            {
                return RecurringPaymentType.NotSupported;
            }
        }

        /// <summary>
        /// Gets a payment method type
        /// </summary>
        public PaymentMethodType PaymentMethodType
        {
            get
            {
                return PaymentMethodType.Button;
            }
        }
        #endregion

    }
}